Next | Prev | Up | Top | Contents | Index
Coordinating Upper-Half and Interrupt Entry Points
Upper-half entry points prepare work for the device to do, and the interrupt routine reports the completion of the device action. In a block device driver, this communication is relatively simple. In a character driver, you have more design options. The kernel functions mentioned in the following topics are covered under "Waiting and Mutual Exclusion".
Coordinating Through the buf_t
In a block device driver, the pfxstrategy() routine initiates a read or a write based on a buf_t structure (see "Entry Point strategy()"), and leaves the address of the buf_t where the interrupt routine can find it. Then pfxstrategy() calls the biowait() kernel function to wait for completion.
The pfxintr() entry point updates the buf_t (using pfxbioerror() if necessary) and then uses biodone() to mark the buf_t as complete. This ends the wait for pfxstrategy(). These kernel functions are multiprocessor-aware.
Coordination in a Character Driver
In a character driver that supports interrupts, you design your own coordination mechanism. The simplest (and not recommended) would be based on using the kernel function sleep() in the upper half, and wakeup() in the interrupt routine. You can also use a semaphore and use psema() in the upper half and vsema() in the interrupt handler.
If you need to allow for timeouts, you have to deal with the complication that the timeout function can be called concurrently with an interrupt. When you use a semaphore, the interrupt routine can use vsema() to post completion, and the timeout function can use cvsema() to post it only if it has not already been posted.
Next | Prev | Up | Top | Contents | Index